'HIDEasy
'Copyright (C) 2011 ASFX

'This program is free software; you can redistribute it and/or
'modify it under the terms of the GNU General Public License
'as published by the Free Software Foundation; either version 2
'of the License, or (at your option) any later version.

'This program is distributed in the hope that it will be useful,
'but WITHOUT ANY WARRANTY; without even the implied warranty of
'MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
'GNU General Public License for more details.

'You should have received a copy of the GNU General Public License
'along with this program; if not, write to the Free Software
'Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
Imports System.Runtime.InteropServices
Imports USAGE = System.UInt16

<CLSCompliant(False)> _
Partial Public Class HIDClass
    Private Const FACILITY_HID_ERROR_CODE% = &H11

    Public Enum HID_ERROR_CODE As Integer
        HIDP_STATUS_SUCCESS = (&H0I << 28) Or (FACILITY_HID_ERROR_CODE% << 16) Or &H0
        HIDP_STATUS_NULL = (&H8I << 28) Or (FACILITY_HID_ERROR_CODE% << 16) Or &H1
        HIDP_STATUS_INVALID_PREPARSED_DATA = (&HCI << 28) Or (FACILITY_HID_ERROR_CODE% << 16) Or &H1
        HIDP_STATUS_INVALID_REPORT_TYPE = (&HCI << 28) Or (FACILITY_HID_ERROR_CODE% << 16) Or &H2
        HIDP_STATUS_INVALID_REPORT_LENGTH = (&HCI << 28) Or (FACILITY_HID_ERROR_CODE% << 16) Or &H3
        HIDP_STATUS_USAGE_NOT_FOUND = (&HCI << 28) Or (FACILITY_HID_ERROR_CODE% << 16) Or &H4
        HIDP_STATUS_VALUE_OUT_OF_RANGE = (&HCI << 28) Or (FACILITY_HID_ERROR_CODE% << 16) Or &H5
        HIDP_STATUS_BAD_LOG_PHY_VALUES = (&HCI << 28) Or (FACILITY_HID_ERROR_CODE% << 16) Or &H6
        HIDP_STATUS_BUFFER_TOO_SMALL = (&HCI << 28) Or (FACILITY_HID_ERROR_CODE% << 16) Or &H7
        HIDP_STATUS_INTERNAL_ERROR = (&HCI << 28) Or (FACILITY_HID_ERROR_CODE% << 16) Or &H8
        HIDP_STATUS_I8042_TRANS_UNKNOWN = (&HCI << 28) Or (FACILITY_HID_ERROR_CODE% << 16) Or &H9
        HIDP_STATUS_INCOMPATIBLE_REPORT_ID = (&HCI << 28) Or (FACILITY_HID_ERROR_CODE% << 16) Or &HA
        HIDP_STATUS_NOT_VALUE_ARRAY = (&HCI << 28) Or (FACILITY_HID_ERROR_CODE% << 16) Or &HB
        HIDP_STATUS_IS_VALUE_ARRAY = (&HCI << 28) Or (FACILITY_HID_ERROR_CODE% << 16) Or &HC
        HIDP_STATUS_DATA_INDEX_NOT_FOUND = (&HCI << 28) Or (FACILITY_HID_ERROR_CODE% << 16) Or &HD
        HIDP_STATUS_DATA_INDEX_OUT_OF_RANGE = (&HCI << 28) Or (FACILITY_HID_ERROR_CODE% << 16) Or &HE
        HIDP_STATUS_BUTTON_NOT_PRESSED = (&HCI << 28) Or (FACILITY_HID_ERROR_CODE% << 16) Or &HF
        HIDP_STATUS_REPORT_DOES_NOT_EXIST = (&HCI << 28) Or (FACILITY_HID_ERROR_CODE% << 16) Or &H10
        HIDP_STATUS_NOT_IMPLEMENTED = (&HCI << 28) Or (FACILITY_HID_ERROR_CODE% << 16) Or &H20
    End Enum

    <StructLayout(LayoutKind.Sequential)> _
    Friend Structure HIDP_CAPS
        Dim Usage As USAGE
        Dim UsagePage As Page
        Dim InputReportByteLength As UShort
        Dim OutputReportByteLength As UShort
        Dim FeatureReportByteLength As UShort

        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=17)> _
        Dim Reserved() As Short

        Dim NumberLinkCollectionNodes As UShort
        Dim NumberInputButtonCaps As UShort
        Dim NumberInputValueCaps As UShort
        Dim NumberInputDataIndices As UShort
        Dim NumberOutputButtonCaps As UShort
        Dim NumberOutputValueCaps As UShort
        Dim NumberOutputDataIndices As UShort
        Dim NumberFeatureButtonCaps As UShort
        Dim NumberFeatureValueCaps As UShort
        Dim NumberFeatureDataIndices As UShort
    End Structure

    <StructLayout(LayoutKind.Sequential)> _
    Friend Structure HIDP_BUTTON_CAPS
        Dim UsagePage As USAGE
        Dim ReportID As Byte

        <MarshalAs(UnmanagedType.I1)> _
        Dim IsAlias As Boolean

        Dim BitField As UShort
        Dim LinkCollection As UShort
        Dim LinkUsage As USAGE
        Dim LinkUsagePage As USAGE

        <MarshalAs(UnmanagedType.I1)> _
        Dim IsRange As Boolean

        <MarshalAs(UnmanagedType.I1)> _
        Dim IsStringRange As Boolean

        <MarshalAs(UnmanagedType.I1)> _
        Dim IsDesignatorRange As Boolean

        <MarshalAs(UnmanagedType.I1)> _
        Dim IsAbsolute As Boolean

        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=20)> _
        Private Reserved() As UInt16

        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=8)> _
        Private RangeData As UInt16()

        Public ReadOnly Property Range() As HIDP_BUTTON_Or_VALUE_CAPS_Range
            Get
                Dim _Range As HIDP_BUTTON_Or_VALUE_CAPS_Range
                With _Range
                    .UsageMin = RangeData(0)
                    .UsageMax = RangeData(1)
                    .StringMin = RangeData(2)
                    .StringMax = RangeData(3)
                    .DesignatorMin = RangeData(4)
                    .DesignatorMax = RangeData(5)
                    .DataIndexMin = RangeData(6)
                    .DataIndexMax = RangeData(7)
                End With
                Return _Range
            End Get
        End Property

        Public ReadOnly Property NotRange() As HIDP_BUTTON_Or_VALUE_CAPS_NotRange
            Get
                Dim _Range As HIDP_BUTTON_Or_VALUE_CAPS_NotRange
                With _Range
                    .Usage = RangeData(0)
                    .Reserved1 = RangeData(1)
                    .StringIndex = RangeData(2)
                    .Reserved2 = RangeData(3)
                    .DesignatorIndex = RangeData(4)
                    .Reserved3 = RangeData(5)
                    .DataIndex = RangeData(6)
                    .Reserved4 = RangeData(7)
                End With
                Return _Range
            End Get
        End Property
    End Structure

    <StructLayout(LayoutKind.Sequential)> _
    Friend Structure HIDP_VALUE_CAPS
        Dim UsagePage As USAGE
        Dim ReportID As Byte

        <MarshalAs(UnmanagedType.I1)> _
        Dim IsAlias As Boolean

        Dim BitField As UShort
        Dim LinkCollection As UShort
        Dim LinkUsage As USAGE
        Dim LinkUsagePage As USAGE

        <MarshalAs(UnmanagedType.I1)> _
        Dim IsRange As Boolean

        <MarshalAs(UnmanagedType.I1)> _
        Dim IsStringRange As Boolean

        <MarshalAs(UnmanagedType.I1)> _
        Dim IsDesignatorRange As Boolean

        <MarshalAs(UnmanagedType.I1)> _
        Dim IsAbsolute As Boolean

        <MarshalAs(UnmanagedType.I1)> _
        Dim HasNull As Boolean

        Private Reserved As Byte
        'UCHAR
        Dim BitSize As UShort
        Dim ReportCount As UShort

        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=5)> _
        Private Reserved2() As UInt16

        Dim UnitsExp As UInt32
        Dim Units As Int32
        'ULong
        Dim LogicalMin As Int32
        Dim LogicalMax As Int32
        Dim PhysicalMin As Int32
        Dim PhysicalMax As Int32

        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=8)> _
        Private RangeData As UInt16()

        Public ReadOnly Property Range() As HIDP_BUTTON_Or_VALUE_CAPS_Range
            Get
                Dim _Range As HIDP_BUTTON_Or_VALUE_CAPS_Range
                With _Range
                    .UsageMin = RangeData(0)
                    .UsageMax = RangeData(1)
                    .StringMin = RangeData(2)
                    .StringMax = RangeData(3)
                    .DesignatorMin = RangeData(4)
                    .DesignatorMax = RangeData(5)
                    .DataIndexMin = RangeData(6)
                    .DataIndexMax = RangeData(7)
                End With
                Return _Range
            End Get
        End Property

        Public ReadOnly Property NotRange() As HIDP_BUTTON_Or_VALUE_CAPS_NotRange
            Get
                Dim _Range As HIDP_BUTTON_Or_VALUE_CAPS_NotRange
                With _Range
                    .Usage = RangeData(0)
                    .Reserved1 = RangeData(1)
                    .StringIndex = RangeData(2)
                    .Reserved2 = RangeData(3)
                    .DesignatorIndex = RangeData(4)
                    .Reserved3 = RangeData(5)
                    .DataIndex = RangeData(6)
                    .Reserved4 = RangeData(7)
                End With
                Return _Range
            End Get
        End Property
    End Structure

    <StructLayout(LayoutKind.Sequential)> _
    Friend Structure HIDP_BUTTON_Or_VALUE_CAPS_Range
        Dim UsageMin As USAGE
        Dim UsageMax As USAGE
        Dim StringMin As UShort
        Dim StringMax As UShort
        Dim DesignatorMin As UShort
        Dim DesignatorMax As UShort
        Dim DataIndexMin As UShort
        Dim DataIndexMax As UShort
    End Structure

    <StructLayout(LayoutKind.Sequential)> _
    Friend Structure HIDP_BUTTON_Or_VALUE_CAPS_NotRange
        Dim Usage As USAGE
        Dim Reserved1 As USAGE
        Dim StringIndex As UShort
        Dim Reserved2 As UShort
        Dim DesignatorIndex As UShort
        Dim Reserved3 As UShort
        Dim DataIndex As UShort
        Dim Reserved4 As UShort
    End Structure

    <StructLayout(LayoutKind.Sequential)> _
    Friend Structure HIDP_DATA
        Dim DataIndex As UInt16
        Private Reserved As UInt16
        Dim Values As HIDP_DATA_Values
    End Structure

    <StructLayout(LayoutKind.Sequential)> _
    Friend Structure HIDP_DATA_Values
        Dim RawValue As UInt32

        Public Property [On] As Boolean
            Get
                Return RawValue <> 0
            End Get
            Set(ByVal value As Boolean)
                If value Then
                    RawValue = UInt32.MaxValue
                Else
                    RawValue = UInt32.MinValue
                End If
            End Set
        End Property
    End Structure

    <StructLayout(LayoutKind.Sequential)> _
    Friend Structure HIDD_ATTRIBUTES
        Dim Size As UInt32
        '  ULONG
        Dim VendorID As UInt16
        Dim ProductID As UInt16
        Dim VersionNumber As UInt16
    End Structure

    <StructLayout(LayoutKind.Sequential)> _
    Friend Structure HIDP_LINK_COLLECTION_NODE
        Dim LinkUsage As USAGE
        Dim LinkUsagePage As USAGE
        Dim Parent As UShort
        Dim NumberOfChildren As UShort
        Dim NextSibling As UShort
        Dim FirstChild As UShort
        Dim CollectionType As CollectionType
        Dim IsAliasAndReserved0 As Byte
        Dim Reserved1 As Byte
        Dim Reserved2 As Byte
        Private UserContext As IntPtr

        Public Function IsAlias() As Boolean
            Return CBool(IsAliasAndReserved0 And &H1)
        End Function
    End Structure

    <StructLayout(LayoutKind.Sequential)> _
    Friend Structure HIDP_UNKNOWN_TOKEN
        Dim Token As Byte
        'UCHAR 
        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=3)> _
        Dim Reserved() As Byte

        'UCHAR
        Dim BitField As UInt32
        'ULong
    End Structure

    <StructLayout(LayoutKind.Sequential)> _
    Friend Structure HIDP_EXTENDED_ATTRIBUTES
        Dim NumGlobalUnknowns As Byte
        'UCHAR
        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=3)> _
        Dim Reserved() As Byte

        'UCHAR
        Private GlobalUnknowns As IntPtr
        'PHIDP_UNKNOWN_TOKEN
        '<MarshalAs(UnmanagedType.ByValArray, SizeConst:=1)> _
        Dim Data As UInt32
        'ULong
    End Structure

    <StructLayout(LayoutKind.Sequential)> _
    Friend Structure USAGE_AND_PAGE
        Dim Usage As USAGE
        Dim UsagePage As USAGE
    End Structure

    Friend Enum HIDP_REPORT_TYPE As UShort
        HidP_Input
        HidP_Output
        HidP_Feature
    End Enum

    Friend Enum CollectionType As Byte
        Physical = &H0
        Application = &H1
        Logical = &H2
        Report = &H3
        Array = &H4
        Switch = &H5
        Usage_Modifier = &H6
        'Reserved = &H7
        'Reserved7F = &H7F
        'Vendor_defined = &H80
        'Vendor_definedFF = &HFF
    End Enum
End Class
